package com.conversationboard.batch.jobs.polls;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import com.conversationboard.database.BatchQueries;
import com.conversationboard.database.Database;
import com.conversationboard.formatter.IllegalMessageException;
import com.conversationboard.logger.LogMessageType;
import com.conversationboard.logger.Logger;
import com.conversationboard.model.Message;
import com.conversationboard.model.NoSuchThreadException;
import com.conversationboard.model.Thread;
import com.conversationboard.model.User;
import com.conversationboard.model.exceptions.DuplicateMessageException;

public class PollBumper implements Job {

	private static class ThreadIdentifier {

		private int boardId;
		private int threadId;


		public ThreadIdentifier(int boardId, int threadId) {
			this.boardId = boardId;
			this.threadId = threadId;
		}


		public int getBoardId() {
			return boardId;
		}


		public int getThreadId() {
			return threadId;
		}

	}


	public void execute(JobExecutionContext context) throws JobExecutionException {

		long startTime = System.currentTimeMillis();

		Connection connection = null;
		List<ThreadIdentifier> tomorrowsPolls = new LinkedList<ThreadIdentifier>();
		List<ThreadIdentifier> todaysPolls = new LinkedList<ThreadIdentifier>();

		try {

			connection = Database.getConnection();

			PreparedStatement statement = connection.prepareStatement(BatchQueries.GET_POLLS_DUE_TOMORROW);
			statement.execute();

			ResultSet tomorrow = statement.getResultSet();

			while (tomorrow.next()) {

				int boardId = tomorrow.getInt("boardid");
				int threadId = tomorrow.getInt("threadid");
				ThreadIdentifier threadIdentifier = new ThreadIdentifier(boardId, threadId);

				tomorrowsPolls.add(threadIdentifier);

			}

			statement.close();

			statement = connection.prepareStatement(BatchQueries.GET_POLLS_DUE_TODAY);
			statement.execute();

			ResultSet today = statement.getResultSet();

			while (today.next()) {

				int boardId = today.getInt("boardid");
				int threadId = today.getInt("threadid");
				ThreadIdentifier threadIdentifier = new ThreadIdentifier(boardId, threadId);

				todaysPolls.add(threadIdentifier);
			}

			statement.close();

			/* Loop through the identified threads and bump them with a message */

			for (ThreadIdentifier threadId : tomorrowsPolls) {

				Thread thread = Thread.get(threadId.getBoardId(), threadId.getThreadId());

				Message message = new Message(thread);
				message.setBoardId(thread.getBoardId());
				message.setThreadId(thread.getThreadId());
				message.setTimestamp(new Date());
				message.setDisplayName("<strong>System</strong>");
				message.setDeleted(false);
				message.setBody("Automatic thread bump. This poll is closing tomorrow.");
				message.setIpAddress("0.0.0.0");
				message.setUserId("noemailaddress");

				thread.addMessage(User.getSystemUser(), message, message.getUserId(), true);
			}

			for (ThreadIdentifier threadId : todaysPolls) {

				Thread thread = Thread.get(threadId.getBoardId(), threadId.getThreadId());

				Message message = new Message(thread);
				message.setBoardId(thread.getBoardId());
				message.setThreadId(thread.getThreadId());
				message.setTimestamp(new Date());
				message.setDisplayName("<strong>System</strong>");
				message.setDeleted(false);
				message.setBody("Automatic thread bump. This poll's results are now in.");
				message.setIpAddress("0.0.0.0");
				message.setUserId("noemailaddress");

				thread.addMessage(User.getSystemUser(), message, message.getUserId(), true);
			}

			long timeTaken = System.currentTimeMillis() - startTime;
			Logger.log(new Date(), "Poll Bumper Job took: " + timeTaken + " milliseconds", null, LogMessageType.DEBUG);

		} catch (NoSuchThreadException e) {
			throw new JobExecutionException(e);
		} catch (DuplicateMessageException e) {
			throw new JobExecutionException(e);
		} catch (IllegalMessageException e) {
			throw new JobExecutionException(e);
		} catch (SQLException e) {
			throw new JobExecutionException(e);
		} finally {
			try {
				Database.close(connection);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

	}
}
